#pragma once
#include <pthread.h>
#include "tcp_socket.hpp"
#include <functional>

typedef std::function<void(const std::string& rep, std::string* resp)> Handler;

struct Threadarg{
    //客户端套接字：用于连接发送数据，接受数据等等，即发出响应
    //客户端ip数据
    TcpSocket new_sock;
    std::string ip;
    uint16_t port;
    Handler handler;
};

class TcpThreadServer
{
public:
    TcpThreadServer(const std::string& ip, uint16_t port):ip_(ip), port_(port)
    {}
    bool Start(Handler handler)
    {   //1.2.3
        CHECK_RET(listen_sock.Socket());
        CHECK_RET(listen_sock.Bind(ip_, port_));
        CHECK_RET(listen_sock.Listen(5));
        //4.
        for(;;)
        {
            //5.accept
            Threadarg* arg = new Threadarg();
            arg->handler = handler;
            bool ret =listen_sock.Accept(&arg->new_sock, &arg->ip, &arg->port);
            if(!ret){
                continue;
            }
            printf("[client %s:%d] connect\n", arg->ip.c_str(), arg->port);
            // 6. 创建新的线程完成具体操作
            pthread_t tid;//threadid   ,  pid: processid
            pthread_create(&tid, NULL, Threadentry, arg);
            pthread_detach(tid);
            //                           pthread_detach!!!!!!!!!
            
            // 线程分离是一种优化手段，用于减少线程管理开销。
            // 当一个线程被分离后，它结束时会自动释放其占用的所有资源，而不需要其他线程来调用pthread_join来回收这些资源。
            // 在服务器应用中，通常会有大量的短生命周期线程被创建来处理客户端的请求。
            // 如果每个线程都需要被主线程显式地等待（通过pthread_join），那么主线程将花费大量的时间在等待线程结束上，而不是处理新的连接请求。
            // 使用线程分离可以简化线程管理，提高服务器的响应速度和吞吐量。
        }
        return true;
    }
    static void* Threadentry(void *arg)
    {
        Threadarg* p = reinterpret_cast<Threadarg*>(arg);
        ProcessConnect(p);
        p->new_sock.Close();
        delete p;
        return NULL;
    }
    static void ProcessConnect(Threadarg* arg)
    {
        for(;;)
        {
            std::string rep;
            bool ret = arg->new_sock.Recv(&rep);
            if (!ret) {
                printf("[client %s:%d] disconnected!\n", arg->ip.c_str(), arg->port);
                break;
            }
            std::string resp;
            // 3. 根据请求计算响应
            printf("diart~~\n");
            arg->handler(rep, &resp);
            //发送响应
            printf("diart~~\n");
            arg->new_sock.Send(resp);//发到new_sock客户端
            printf("[client %s:%d] req: %s, resp: %s\n", arg->ip.c_str(),arg->port, rep.c_str(), resp.c_str());
        }
    }
private:
    //服务端的ip数据
    TcpSocket listen_sock;//服务端监听套接字：反馈响应
    std::string ip_;
    uint16_t port_;
};